﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.ServiceProcess;

namespace CheckMemcached
{
    public partial class CheckMemcached : ServiceBase
    {
        List<ErrorServer> ListErrorService = new List<ErrorServer>();
        System.Timers.Timer CheckTimer;
        System.Timers.Timer SendMailTimer;
        bool isSendMail = false;

        public CheckMemcached()
        {
            CheckTimer = new System.Timers.Timer();
            CheckTimer.Elapsed += new System.Timers.ElapsedEventHandler(CheckTimer_Elapsed);

            SendMailTimer = new System.Timers.Timer();
            SendMailTimer.Elapsed += new System.Timers.ElapsedEventHandler(SendMailTimer_Elapsed);
            SendMailTimer.Interval = GetConfig.SendMailRepeatMinute() * 60 * 1000;

            InitializeComponent();
        }

        void SendMailTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            isSendMail = false;
        }

        protected override void OnStart(string[] args)
        {
            CheckTimer.Interval = GetConfig.RepeatMinute() * 60000;
            CheckTimer.Enabled = true;
            CheckTimer.Start();

            SendMailTimer.Enabled = true;
            SendMailTimer.Start();
        }

        protected override void OnStop()
        {
            CheckTimer.Enabled = false;
            CheckTimer.Stop();
        }

        protected override void OnPause()
        {
            CheckTimer.Enabled = false;
            CheckTimer.Stop();
        }

        protected override void OnContinue()
        {
            CheckTimer.Enabled = true;
            CheckTimer.Start();
        }

        private void CheckTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            try
            {
                CheckSocket cs = new CheckSocket();
                foreach (Server server in GetConfig.GetMemcachedServer())
                {
                    SocketEnum se = cs.Connect(server);
                    if (se == SocketEnum.Exception || se == SocketEnum.TimeOut)
                    {
                        ErrorServer es = new ErrorServer();
                        es.Host = server.Host;
                        es.Port = server.Port;
                        es.CheckTime = DateTime.Now;
                        ListErrorService.Add(es);
                        if (server.IsLocalService)
                        {
                            ResterMemcachedService();
                        }
                        else
                        {
                            ResterNetWorkMemcachedService(server);
                        }
                    }
                    WriteEventLog(se, server);
                }

                if (ListErrorService.Count > 0 && !isSendMail)
                {
                    GetConfig.SendMail(ListErrorService);
                    isSendMail = true;
                    ListErrorService.Clear();
                }
            }
            catch (Exception ex)
            {
                CheckMemcachedLog.WriteEntry(ex.Message, EventLogEntryType.Error, 1);
            }
        }

        /// <summary>
        /// 写日志
        /// </summary>
        /// <param name="se"></param>
        /// <param name="server"></param>
        private void WriteEventLog(SocketEnum se, Server server)
        {
            string LogString = "Memcached Service({0}:{1}) at {2} check {3}";
            string Question = string.Empty;
            EventLogEntryType eet = EventLogEntryType.SuccessAudit;
            switch (se)
            {
                case SocketEnum.Exception:
                    Question = "not service";
                    eet = EventLogEntryType.Error;
                    break;
                case SocketEnum.Success:
                    Question = "Success";
                    eet = EventLogEntryType.SuccessAudit;
                    break;
                case SocketEnum.TimeOut:
                    Question = "connection TimeOut";
                    eet = EventLogEntryType.Error;
                    break;
            }
            LogString = string.Format(LogString, server.Host, server.Port, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Question);
            if (se == SocketEnum.Success)
            {
                if (GetConfig.IsWriteSuccessEventLog())
                {
                    CheckMemcachedLog.WriteEntry(LogString, eet);
                }
            }
            else
            {
                CheckMemcachedLog.WriteEntry(LogString, eet);
            }
        }

        /// <summary>
        /// 重启Memcached
        /// </summary>
        private void ResterMemcachedService()
        {
            if (!GetConfig.IsRestartServier())
            {
                return;
            }
            try
            {
                ServiceController[] sc = ServiceController.GetServices();
                foreach (ServiceController _sc in sc)
                {
                    if (_sc.ServiceName.ToLower() == "memcached Server".ToLower())
                    {
                        if (_sc.Status != ServiceControllerStatus.Running)
                        {
                            _sc.Start();
                            if (GetConfig.IsWriteSuccessEventLog())
                            {
                                CheckMemcachedLog.WriteEntry("memcached Server Rester Success(Local)", EventLogEntryType.Information, 0);
                            }
                        }
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                CheckMemcachedLog.WriteEntry("memcached Server Rester Error(Local):" + ex.Message, EventLogEntryType.Error, 0);
            }
        }


        /// <summary>
        /// 启动远程Memcached服务
        /// </summary>
        /// <param name="server">服务器</param>
        private void ResterNetWorkMemcachedService(Server server)
        {
            if (string.IsNullOrEmpty(server.User) || string.IsNullOrEmpty(server.Password) || !GetConfig.IsRestartServier())
            {
                return;
            }
            try
            {
                Process process = new Process();
                process.StartInfo.FileName = "cmd.exe";
                process.StartInfo.CreateNoWindow = false;
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardError = true;
                process.StartInfo.RedirectStandardInput = true;
                process.StartInfo.RedirectStandardOutput = true;

                process.Start();

                process.StandardInput.AutoFlush = true;

                string cmd = string.Format("net use \\\\{0}\\ipc$ {1} /user:{2}", server.Host, server.Password, server.User);
                process.StandardInput.WriteLine(cmd);

                cmd = string.Format("sc \\\\{0} start \"memcached Server\"", server.Host);
                process.StandardInput.WriteLine(cmd);
                process.StandardInput.Close();
                if (GetConfig.IsWriteSuccessEventLog())
                {
                    CheckMemcachedLog.WriteEntry("Rester Memcached Service Success(" + server.Host + "):\r\n" + process.StandardOutput.ReadToEnd(), EventLogEntryType.Information, 1);
                }
            }
            catch (Exception ex)
            {
                CheckMemcachedLog.WriteEntry("Rester Memcached Service Error(" + server.Host + "):\r\n" + ex.Message, EventLogEntryType.Error, 1);
            }
        }
    }
}
